#include "mainwindow.h"
#include "./ui_mainwindow.h"

#include <QTimer>
#include <QClipboard>
#include <QCursor>
#include <QMessageBox>
#include <QDesktopServices>
#include <QProcess>
#include <QFileDialog>
#include <QFileInfo>
#include <QCloseEvent>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , timer(new QTimer(this))
    , popup_menu(new QMenu(this))
    , appname("Kronometer(clone)")
{
    ui->setupUi(this);

    filename = "untitled";
    filepath = "";
    setWindowTitle(QString("%1 - %2").arg(appname).arg(filename));

    ui->tableWidget->setHorizontalHeaderLabels({tr("Lap #"), tr("Lap Time"), tr("Note")});

    connect(ui->actionResume, &QAction::triggered, this, &MainWindow::on_start_clicked);
    connect(ui->actionPause, &QAction::triggered, this, &MainWindow::on_pause_clicked);
    connect(ui->actionReset, &QAction::triggered, this, &MainWindow::on_reset_clicked);
    connect(ui->actionLap, &QAction::triggered, this, &MainWindow::on_lap_clicked);

    timer->setInterval(10);  // 10ms
    elapsed = 0;
    current_timestamp = "00:00.00";
    connect(timer, &QTimer::timeout, this, &MainWindow::update);

    lap_count = 0;

    connect(ui->actionCopy, &QAction::triggered, this, [&]() {QGuiApplication::clipboard()->setText(current_timestamp);});
    connect(ui->actionShow_Toolbar, &QAction::triggered, this, [&](bool checked){ui->toolBar->setVisible(checked);});
    connect(ui->actionShow_Menubar, &QAction::triggered, this, [&](bool checked){
        ui->menubar->setVisible(checked);
        ui->actionOpenMenu->setVisible(!checked);
    });

    is_new_file = true;
    connect(ui->actionSave, &QAction::triggered, this, &MainWindow::on_save_clicked);
    connect(ui->actionSave_As, &QAction::triggered, this, &MainWindow::on_save_as_clicked);
    connect(ui->actionExport_Laps_as, &QAction::triggered, this, &MainWindow::on_export_clicked);
    connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::on_open_clicked);

    // -INIT POPUP MENU
    popup_menu->addAction(ui->actionNew);
    popup_menu->addAction(ui->actionOpen);
    popup_menu->addSeparator();
    popup_menu->addAction(ui->actionSave);
    popup_menu->addAction(ui->actionSave_As);
    popup_menu->addSeparator();
    popup_menu->addAction(ui->actionExport_Laps_as);
    popup_menu->addSeparator();
    popup_menu->addAction(ui->actionCopy);
    popup_menu->addSeparator();
    popup_menu->addAction(ui->actionConfigure_Keyboard_Shortcuts);
    popup_menu->addAction(ui->actionConfigure_Toolbars);
    popup_menu->addAction(ui->actionConfigure_Kronometer);
    popup_menu->addMenu(ui->menuHelp);
    popup_menu->addSeparator();
    popup_menu->addAction(ui->actionShow_Menubar);
    connect(ui->actionOpenMenu, &QAction::triggered, this, [&]() {popup_menu->popup(QCursor::pos());});

    // -MISC
    connect(ui->actionConfigure_Language, &QAction::triggered, this, []() {qDebug() << "TODO";});
    connect(ui->actionKronometer_Handbook, &QAction::triggered, this, []() {QDesktopServices::openUrl(QUrl("https://docs.kde.org/?application=kronometer"));});
    connect(ui->actionReport_Bug, &QAction::triggered, this, []() {QDesktopServices::openUrl(QUrl("https://gitcode.com/razorrazor/"));});
    connect(ui->actionDonate, &QAction::triggered, this, []() {QDesktopServices::openUrl(QUrl("https://kde.org/donate/"));});
    connect(ui->actionAbout_Qt, &QAction::triggered, this,  [&]() {QMessageBox::aboutQt(this);});
    connect(ui->actionAbout_Kronometer, &QAction::triggered, this, [&]() {
        QMessageBox::about(this, tr("About Kronometer(clone)"), tr("Kronometer(clone)\n---\nAuthor zhumo\nEmail zhumo25@outlook.com\nThanks using!"));
    });

    connect(ui->actionNew, &QAction::triggered, this, []() {qDebug() << QProcess::startDetached(QCoreApplication::applicationFilePath());});
    connect(ui->actionQuit, &QAction::triggered, this, []() {QCoreApplication::quit();});

    connect(ui->tableWidget, &QTableWidget::itemDoubleClicked, this, [&](QTableWidgetItem *item) {
        if (item->flags() & Qt::ItemIsEditable)
            file_changed();
    });
}

void MainWindow::on_start_clicked() {
    file_changed();

    ui->actionResume->setEnabled(false);
    ui->actionPause->setEnabled(true);
    ui->actionReset->setEnabled(true);
    ui->actionLap->setEnabled(true);
    timer->start();
}

void MainWindow::on_pause_clicked() {
    ui->actionResume->setText(tr("Resume"));
    ui->actionResume->setEnabled(true);
    ui->actionPause->setEnabled(false);
    ui->actionLap->setEnabled(false);
    timer->stop();
}

void MainWindow::on_reset_clicked() {
    ui->actionResume->setText(tr("Start"));
    ui->actionResume->setEnabled(true);
    ui->actionPause->setEnabled(false);
    ui->actionReset->setEnabled(false);
    ui->actionLap->setEnabled(false);

    timer->stop();
    elapsed = 0;
    update_ui_labels();

    for (int i = lap_count-1; i >= 0; --i)
        ui->tableWidget->removeRow(i);
    lap_count = 0;
}

void MainWindow::add_lap_item(QString const id, QString const timestamp, QString const note) {
    ui->tableWidget->setSortingEnabled(false);

    ui->tableWidget->setRowCount(lap_count+1);

    auto count_item = new QTableWidgetItem(id);
    count_item->setTextAlignment(Qt::AlignCenter);
    count_item->setFlags(Qt::NoItemFlags);
    ui->tableWidget->setItem(lap_count, 0, count_item);

    auto timestamp_item = new QTableWidgetItem(timestamp);
    timestamp_item->setTextAlignment(Qt::AlignCenter);
    timestamp_item->setFlags(Qt::NoItemFlags);
    ui->tableWidget->setItem(lap_count, 1, timestamp_item);

    auto note_item = new QTableWidgetItem(note);
    note_item->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled);
    ui->tableWidget->setItem(lap_count, 2, note_item);

    ui->tableWidget->setSortingEnabled(true);

    ++lap_count;
}

void MainWindow::on_lap_clicked() {
    file_changed();
    add_lap_item(QString("%1").arg(lap_count+1), current_timestamp, "");
}

void MainWindow::on_save_clicked() {
    if (is_new_file) {
        filepath = QFileDialog::getSaveFileName(this, tr("Save Data"), "/home/", tr("Data Files (*.csv)"));
        if (filepath.length() == 0)
            return;
        filename = QFileInfo(filepath).baseName();
    }

    write_csv_file(filepath);

    file_saved();
    is_new_file = false;
}

void MainWindow::on_save_as_clicked() {
    write_csv_file(QFileDialog::getSaveFileName(this, tr("Save As Data"), "/home/", tr("Data Files (*.csv)")));
}

void MainWindow::on_export_clicked() {
    write_json_file(QFileDialog::getSaveFileName(this, tr("Export Data"), "/home/", tr("Data Files (*.json)")));
}

void MainWindow::on_open_clicked() {
    auto path = QFileDialog::getOpenFileName(this, tr("Open Data"), "/home/", tr("Data Files (*.csv)"));
    if (path.length() == 0 || path == filepath || need_save_file())
        return;
    filepath = path;
    filename = QFileInfo(filepath).fileName();
    read_csv_file(filepath);
    is_new_file = false;
    file_saved();
}

void MainWindow::update() {
    elapsed += 10;
    update_ui_labels();
}

bool MainWindow::need_save_file() {
    if (!ui->actionSave->isEnabled())
        return false;

    return QMessageBox::question(this, tr("Confirm Quit"), tr("Do you want to quit and lose your unsaved times?"))
        == QMessageBox::No;
}

void MainWindow::closeEvent(QCloseEvent *event) {
    if (need_save_file()) {
        event->ignore();
    }
    else
        QMainWindow::closeEvent(event);
}

void MainWindow::update_ui_labels() {
    int temp = elapsed % (60*60*1000);
    int minutes = temp / (60*1000);
    temp %= (60*1000);
    int seconds = temp / 1000;
    temp %= 1000;
    int hundredths = temp / 10;

    QString minutes_str = QString::number(minutes).rightJustified(2, '0');
    QString seconds_str = QString::number(seconds).rightJustified(2, '0');
    QString hundredths_str = QString::number(hundredths).rightJustified(2, '0');
    current_timestamp = QString("%1:%2.%3").arg(minutes_str).arg(seconds_str).arg(hundredths_str);
    ui->label_minutes_num->setText(minutes_str);
    ui->label_seconds_num->setText(seconds_str);
    ui->label_hundredths_num->setText(hundredths_str);
}

void MainWindow::file_changed() {
    ui->actionSave->setEnabled(true);
    ui->actionSave_As->setEnabled(true);
    ui->actionExport_Laps_as->setEnabled(true);
    setWindowTitle(QString("%1 - %2*").arg(appname).arg(filename));
}

void MainWindow::file_saved() {
    ui->actionSave->setEnabled(false);
    ui->actionSave_As->setEnabled(true);
    ui->actionExport_Laps_as->setEnabled(true);
    setWindowTitle(QString("%1 - %2").arg(appname).arg(filename));
}

void MainWindow::write_csv_file(QString const path) {
    QFile file(path);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "Can't open file to write!!!" << path;
        return;
    }

    QTextStream out(&file);
    out << "Lap #,Lap Time,Note,\n";
    for (int i = 0; i < ui->tableWidget->rowCount(); ++i) {
        out << ui->tableWidget->item(i, 0)->text() << ","
            << ui->tableWidget->item(i, 1)->text() << ","
            << ui->tableWidget->item(i, 2)->text() << ",\n";
    }
}

void MainWindow::write_json_file(QString const path) {
    QFile file(path);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "Can't open file to write!!!" << path;
        return;
    }

    QTextStream out(&file);
    QJsonArray array;
    for (int i = 0; i < ui->tableWidget->rowCount(); ++i) {
        array.append(QJsonObject{
            {"#", ui->tableWidget->item(i, 0)->text()},
            {"lap", ui->tableWidget->item(i, 1)->text()},
            {"note", ui->tableWidget->item(i, 2)->text()},
        });
    }
    out << QJsonDocument(array).toJson();
}

void MainWindow::read_csv_file(QString const path) {
    QFile file(path);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Can't open file to read!!!" << path;
        return;
    }

    on_reset_clicked();  // -RESET

    int line_count = 0;
    while (!file.atEnd()) {
        if (line_count++ == 0) {
            Q_UNUSED(file.readLine());  // skip header
        }
        auto item = file.readLine().split(u',');
        if (item.length() >= 3) {
            add_lap_item(item[0], item[1], item[2]);
        }
        else
            qDebug() << "Can't pause data item!!!" << item;
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}
